/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.inspur.edp.lcm.metadata.core.persistence;

import com.inspur.edp.lcm.metadata.api.mvnEntity.MavenPackageRefs;
import com.inspur.edp.lcm.metadata.common.FileServiceImp;
import com.inspur.edp.lcm.metadata.common.MavenUtils;
import com.inspur.edp.lcm.metadata.core.entity.PackageType;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.DistributionManagement;
import org.apache.maven.model.Model;
import org.apache.maven.model.Parent;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;

public class PomRepository {
    private final String groupId = "com.inspur.edp";
    private final String artifactId = "download-tools";
    private final String version = "0.1.0-SNAPSHOT";
    private final String modelVersion = "4.0.0";
    private final String packaging = "pom";

    FileServiceImp fileServiceImp = new FileServiceImp();

    public Model getModel(String pomPath) {
        try (FileInputStream fis = new FileInputStream(pomPath)) {
            MavenXpp3Reader reader = new MavenXpp3Reader();
            final Model model = reader.read(fis);
            return model;
        } catch (IOException | XmlPullParserException e) {
            e.printStackTrace();
        }
        return null;
    }

    public void writeModel(String pomPath, Model model) {
        File pom = new File(pomPath);
        if (!pom.exists()) {
            pom.getParentFile().mkdirs();
            try {
                pom.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try (FileOutputStream fileOutputStream = new FileOutputStream(pomPath)) {
            MavenXpp3Writer mavenXpp3Writer = new MavenXpp3Writer();
            mavenXpp3Writer.write(fileOutputStream, model);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public void createPomForDependencyCopy(List<MavenPackageRefs> refs, String pomPath) {
        // 创建pom文件
        fileServiceImp.createFile(pomPath);
        // 创建model并写入
        final List<Dependency> dependencies = createDependencies(refs, PackageType.zip.toString());
        final Model model = createModel(groupId, artifactId, version, modelVersion, packaging, dependencies);
        writeModel(pomPath, model);
    }

    public void updatePom(String pomPath, List<MavenPackageRefs> refs, String packaging) {
        Model model = getModel(pomPath);
        model.setPackaging(packaging);
        final List<Dependency> dependencies = createDependencies(refs, PackageType.jar.toString());
        model.setDependencies(dependencies);
        writeModel(pomPath, model);
    }

    public Model createModelWithSourceModel(Model sourceModel, String repoId, String dependencyVersion) {
        Model model = new Model();

        Parent parent = createParent();
        model.setParent(parent);

        model.setGroupId(sourceModel.getGroupId());
        model.setArtifactId(sourceModel.getArtifactId());
        model.setVersion(sourceModel.getVersion().startsWith("m") ? sourceModel.getVersion() : "m" + sourceModel.getVersion());

        model.setModelVersion("4.0.0");
        model.setPackaging("metadata-pack");

        final boolean isSnotshot = sourceModel.getVersion().endsWith(MavenUtils.SNAP_SHOT);
        DistributionManagement distributionManagement = RepositoryFactory.getInstance().getMavenSettingsRepository().getDistributionManagement(repoId, isSnotshot);
        model.setDistributionManagement(distributionManagement);

        List<Dependency> list = model.getDependencies();
        if (sourceModel.getDependencies() != null && sourceModel.getDependencies().size() > 0) {
            sourceModel.getDependencies().forEach(sourceDependency -> {
                Dependency dependency = new Dependency();
                dependency.setGroupId(sourceDependency.getGroupId());
                dependency.setArtifactId(sourceDependency.getArtifactId());
                boolean dependencyVersionFlag = dependencyVersion != null && sourceDependency.getVersion().endsWith(MavenUtils.SNAP_SHOT);
                String actingVersion = "m" + (dependencyVersionFlag ? dependencyVersion : sourceDependency.getVersion());
                dependency.setVersion(actingVersion);
                dependency.setType("zip");
            });
        }
        model.setDependencies(list);
        return model;
    }

    private Model createModel(String groupId, String artifactId, String version, String modelVersion, String packaging,
        List<Dependency> dependencies) {
        Model model = new Model();
        model.setArtifactId(groupId);
        model.setGroupId(artifactId);
        model.setVersion(version);
        model.setModelVersion(modelVersion);
        model.setPackaging(packaging);
        model.setDependencies(dependencies);
        return model;
    }

    private List<Dependency> createDependencies(List<MavenPackageRefs> refs, String dependencyType) {
        List<Dependency> dependencies = new ArrayList<>();
        refs.forEach(ref -> {
            Dependency dependency = new Dependency();
            dependency.setArtifactId(ref.getArtifactId());
            dependency.setGroupId(ref.getGroupId());
            dependency.setVersion(ref.getVersion());
            dependency.setType(dependencyType);
            dependencies.add(dependency);
        });
        return dependencies;
    }

    private Parent createParent() {
        final Parent parent = new Parent();
        parent.setArtifactId("metadata-parent");
        parent.setGroupId("com.inspur.edp");
        parent.setVersion("0.1.0");
        return parent;
    }
}
